オートスケール時のデプロイを User Data と Capistrano を使って行う(BootStrap パターン)
Auto Scaling を使った構成の場合、EC2 へのデプロイはどうやっているでしょうか?
AWS を使ってる方はご存知の方も多いと思いますが、EC2 には User Data という仕組みがあります。
User Data は、インスタンス起動時にタスクやスクリプトを実行する仕組みです。
今回この User Data を使って、自分自身のインスタンスから最新のソースを GitHub から取得してデプロイする方法についてご紹介したいと思います。
図で表すと以下のイメージですかね。
ssh localhost?
デプロイツールには Capistrano を使いますが、Capistrano は、デプロイ対象のサーバーに対してまず ssh で login を行います。
その後、サーバー上でデプロイ対象のコードの取得や、サービスの再起動をしたりしますが、
AutoScaling は自動でインスタンスが起動するので、どうやってデプロイさせるかがポイントです。
トリガーなどで外のインスタンスからデプロイしてもいいのですが、なるべく疎結合にすべきだと思うので、
自分自身(localhost)からデプロイを行うようにしてみます。
アプリケーション実行ユーザとして、deploy という名前のユーザを作って、localhost から ssh 出来るようにします。
# useradd -m deploy # su - deploy $ ssh-keygen $ cd .ssh && mv id_rsa.pub authorized_keys $ chmod 600 authorized_keys
上記の設定が済んだら、localhost にログイン出来るか試してみましょう。
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ ssh localhost The authenticity of host 'localhost (127.0.0.1)' can't be established. ECDSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts. Last login: Tue Jul 8 13:05:16 2014 from localhost __| __|_ ) _| ( / Amazon Linux AMI ___|\___|___| https://aws.amazon.com/amazon-linux-ami/2014.03-release-notes/ [ec2-user@ip-xxx-xxx-xxx-xxx ~]$
フィンガープリントの確認後、無事ログイン出来ましたね。
しかしここで 1 点注意点があります。EC2 は AMI から起動すると毎回ホスト鍵が変わるため、Capistrano からログインを行う際に、再度フィンガープリントの確認が対話的に行われてしまい、デプロイが上手くいかないのです。
これを解決するために、~/.ssh/config に以下を追記しておきましょう。
Host * StrictHostKeyChecking no UserKnownHostsFile /dev/null
これでフィンガープリントのチェックを行わなくなります。
Capistrano
デプロイするサンプルは Rails のアプリケーションです。 Gemfile の一部を抜粋すると、以下の通りです。
source 'https://rubygems.org' gem 'rails', '4.1.2' group :development do gem 'capistrano', require: false gem 'capistrano-rbenv', require: false gem 'capistrano-bundler', require: false gem 'capistrano-rails', require: false end
localhost からのデプロイ用に config/deploy 以下に local.rb というファイルを作りました。
# config/deploy/local.rb server 'localhost', user: 'deploy', roles: %i(web app db) set :branch, 'master' set :rails_env, :production
そして、EC2上のデプロイ実行用のコードとアプリケーション実行元の場所はそれぞれ以下のようにしました。
- デプロイ実行用のコード: /home/deploy/my_rails_app
- アプリケーション実行元(デプロイ先): /data/my_rails_app
EC2 上からデプロイできる事を確認しておきましょう。
$ cd ~/my_rails_app $ bundle install --path vendor/bundle --without production staging $ bundle exec local deploy ... INFO [b47eea5f] Finished in 0.037 seconds with exit status 0 (successful).
デプロイ用シェル
デプロイの確認が上手く行ったら、User Data から呼び出すシェルを作成します。
折角なので、staging と production をパラメータで切り替えられるようにしておきます。 *1
#!/bin/bash # # /data/bin/startup.sh # ####################### app_root=/data/my_rails_app/current/ source_path=$1 rails_env=$2 cd $source_path git fetch --all git reset --hard origin/master bundle install --path vendor/bundle --without production staging --quiet -j8 bundle exec cap local-$rails_env deploy
Capistrano のファイルも、以下のように production と staging 用で分けました。 *2
local-production.rb
# config/deploy/local-procution.rb server 'localhost', user: 'deploy', roles: %i(web app db) set :branch, 'master' set :rails_env, :production
local-staging.rb
# config/deploy/local-staging.rb server 'localhost', user: 'deploy', roles: %i(web app db) set :branch, 'master' set :rails_env, :staging
これによって以下の指定でデプロイ出来るようになりました。
$ /data/bin/startup.sh /home/deploy/my_rails_app/ production|staging
User Data からシェルを呼び出す
マネージメントコンソールを開いて、User Data を指定します。
2 行目はログ出力用の指定です。
User Data は root ユーザとして実行されるので、su で deploy ユーザを指定しています。
実行結果を見てみる
インスタンスを AMI から起動したら、実行結果を確認してみましょう。
ログは、/var/log/user-data.log に書かれています。
+ su - deploy /data/bin/startup.sh /home/deploy/my_rails_app/ production ... INFO[9fdf606a] Finished in 0.041 seconds with exit status 0 (successful).
無事デプロイが終わったようです!
AutoScaling で実行するには?
Auto Scaling で User Data を実行するには、launch config の作成時に指定が必要です。
以下は、aws cli を使って指定する例になります。
$ aws autoscaling create-launch-configuration \ > --launch-configuration-name "my-lc" \ > --image-id "ami-xxxxxxxx" \ > --user-data "/path/to/user-data.txt" \ > --instance-type "t2.micro"
まとめ
User Data を使って自動でデプロイする方法を紹介しました。一般的に BootStrap パターンと呼ばれたりします。
要点を掻い摘んで紹介しましたが、実際には Web サーバの設定や AMI の作成など他の準備も必要です。
こちらで紹介したパターン以外にも、稼働している EC2 とは別で新しいインスタンス群を用意して、DNS の向き先を切り替えるパターンなどもあります。
実際に production 環境で使う際は、更新しているソースが多かったりすると、デプロイに時間が掛かったりするので、その辺りは工夫が必要かと思います。